package com.example.service.impl;

import com.example.entity.auth.Account;
import com.example.entity.auth.Forget;
import com.example.entity.auth.Register;
import com.example.mapper.AccountMapper;
import com.example.service.AuthorizeService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Optional;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class AuthorizeServiceImpl implements AuthorizeService {

    @Value("${spring.mail.username}")
    String form;

    @Resource
    private final AccountMapper accountMapper;

    @Resource
    MailSender mailSender;

    @Resource
    StringRedisTemplate template;


    BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

    public AuthorizeServiceImpl(AccountMapper accountMapper) {
        this.accountMapper = accountMapper;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if(username == null)
            throw new UsernameNotFoundException("用户名不能为空");
        Account account = accountMapper.findByNameOrEmail(username);
        if (account == null)
            throw new UsernameNotFoundException("用户名或密码错误");
        return User
                .withUsername(account.getUsername())
                .password(account.getPassword())
                .roles("user")
                .build();
    }

    @Override
    public boolean checkUsernameExist(String username) {
        Account account = accountMapper.findByNameOrEmail(username);
        if (account == null){
            return true;
        }else {
            return false;
        }
    }

    @Override
    public String sendValidateEmail(String email,String sessionId,boolean hasAccount) {
        String key = "email:" + sessionId + ":" + email + ":" + hasAccount;
        if (Boolean.TRUE.equals(template.hasKey(key))){
            Long expire = Optional.ofNullable(template.getExpire(key,TimeUnit.SECONDS)).orElse(0L);
            if (expire > 120){
                return "请求频繁，请稍后再试";
            }
        }
        Account account = accountMapper.findByNameOrEmail(email);
        if ( account != null && !hasAccount){
            return "该邮箱已被注册";
        }
        if (account == null && hasAccount){
            return "没有此邮箱地址的账户";
        }
        Random random = new Random();
        int code = random.nextInt(899999) + 100000;
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setFrom(form);
        mailMessage.setTo(email);
        mailMessage.setSubject("您的验证邮件");
        mailMessage.setText("验证码是："+ code);
        try {
            mailSender.send(mailMessage);
            template.opsForValue().set(key,String.valueOf(code),3, TimeUnit.MINUTES);
            return null;
        }catch (MailException e){
            e.printStackTrace();
            return "邮件发送失败，请联系管理员";
        }
    }

    @Override
    public String validateAndRegister(Register register, String sessionId) {
        String email = register.getEmail();
        String key = "email:" + sessionId + ":" + email + ":false";
        if (Boolean.TRUE.equals(template.hasKey(key))){
            String s = template.opsForValue().get(key);
            if (s == null)
                return "验证码失效,请重新申请";
            if (s.equals(register.getCode())){
                register.setPassword(encoder.encode(register.getPassword()));
                template.delete(key);
                int result = accountMapper.createAccount(register.getUsername(), register.getPassword(),register.getEmail());
                if (result > 0){
                    return null;
                }else {
                    return "服务器内部错误，请联系管理员";
                }
            }else {
                return "验证码错误，请检查";
            }
        }else {
            return "请先获取验证码";
        }
    }

    @Override
    public String validateAndResetPassword(Forget forget, String sessionId) {
        String email = forget.getEmail();
        String key = "email:" + sessionId + ":" + email + ":true";
        if (Boolean.TRUE.equals(template.hasKey(key))){
            String s = template.opsForValue().get(key);
            if (s == null)
                return "验证码失效,请重新申请";
            if (s.equals(forget.getCode())){
                forget.setPassword(encoder.encode(forget.getPassword()));
                template.delete(key);
                int result = accountMapper.resetPassword(forget.getPassword(),forget.getEmail());
                if (result > 0){
                    return null;
                }else {
                    return "服务器内部错误，请联系管理员";
                }
            }else {
                return "验证码错误，请检查";
            }
        }else {
            return "请先获取验证码";
        }
    }
}
